package com.xique.park.service.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.EasyExcelFactory;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xique.common.core.web.domain.PageResult;
import com.xique.park.bean.domain.ParkSettlementRecord;
import com.xique.park.bean.dto.ParkSettlementRecordExportDto;
import com.xique.park.bean.dto.SettlementStatisticsDto;
import com.xique.park.bean.request.web.record.SettlementRecordRequest;
import com.xique.park.constant.ExcelConstant;
import com.xique.park.mapper.ParkSettlementRecordMapper;
import com.xique.park.service.service.IParkSettlementRecordService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.List;

/**
 * 结算记录服务实现类
 *
 * @author WLD
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class ParkSettlementRecordServiceImpl extends ServiceImpl<ParkSettlementRecordMapper, ParkSettlementRecord> implements IParkSettlementRecordService {

    private final ParkSettlementRecordMapper parkSettlementRecordMapper;

    @Override
    public PageResult selectPageList(SettlementRecordRequest settlementRecordRequest) {
        // 分页查询
        IPage<ParkSettlementRecord> pageList = selectPage(settlementRecordRequest);

        List<ParkSettlementRecord> parkSettlementRecordList = pageList.getRecords();
        if (CollUtil.isEmpty(parkSettlementRecordList)) {
            return PageResult.getEmptyInstance(settlementRecordRequest.getPageNum(), settlementRecordRequest.getPageSize());
        }

        // 统计金额
        SettlementStatisticsDto settlementStatisticsDto = statisticsAmount(settlementRecordRequest);

        return PageResult
                .builder()
                .pageNum(settlementRecordRequest.getPageNum())
                .pageSize(settlementRecordRequest.getPageSize())
                .totalPages(pageList.getPages())
                .totalSize(pageList.getTotal())
                .list(pageList.getRecords())
                .num(settlementStatisticsDto.getTotalOrderCount())
                .totalPrice(settlementStatisticsDto.getTotalOrderAmount())
                .totalPayPrice(settlementStatisticsDto.getTotalPayAmount())
                .totalServiceCharge(settlementStatisticsDto.getTotalServiceCharge())
                .totalSettlementAmount(settlementStatisticsDto.getTotalSettlementAmount())
                .totalPaymentAmount(settlementStatisticsDto.getTotalPaymentAmount())
                .build();
    }

    @Override
    public void exportList(SettlementRecordRequest settlementRecordRequest, HttpServletResponse response) {
        // 导出的记录总数
        long totalSize = getCount(settlementRecordRequest);
        if (totalSize > 0) {
            long totalPages = totalSize / ExcelConstant.PER_WRITE_ROW_COUNT + 1;
            log.info("[结算记录]-excel导出，请求参数：{}，总条数：{}，总页数：{}，每页数量：{}", settlementRecordRequest, totalSize, totalPages, ExcelConstant.PER_WRITE_ROW_COUNT);

            ExcelWriter excelWriter = null;
            try {
                String fileName = URLEncoder.encode("结算记录.xlsx", "UTF-8");

                response.setCharacterEncoding("UTF-8");
                response.setHeader("Content-disposition", "attachment; filename=" + fileName);
                response.setContentType("application/x-xls");

                OutputStream out = response.getOutputStream();
                excelWriter = EasyExcelFactory.write(out, ParkSettlementRecordExportDto.class).build();

                for (int pageNum = 1; pageNum <= totalPages; pageNum++) {
                    long startTime = System.currentTimeMillis();

                    log.info("[结算记录]-excel导出,开始到导出第{}页", pageNum);

                    // 分页查询结算记录
                    settlementRecordRequest.setPageNum(pageNum);
                    settlementRecordRequest.setPageSize(ExcelConstant.PER_WRITE_ROW_COUNT);
                    IPage<ParkSettlementRecordExportDto> settlementRecordExportDtoPage = selectExportPage(settlementRecordRequest);
                    List<ParkSettlementRecordExportDto> parkSettlementRecordList = settlementRecordExportDtoPage.getRecords();

                    // 导出
                    WriteSheet writeSheet = EasyExcelFactory.writerSheet(pageNum, "结算记录" + pageNum).build();
                    excelWriter.write(parkSettlementRecordList, writeSheet);

                    log.info("[结算记录]-excel导出,第{}页到导出完成，耗时：{}", pageNum, System.currentTimeMillis() - startTime);
                }
            } catch (UnsupportedEncodingException e) {
                log.error("[结算记录]-excel导出，编码格式错误");
                e.printStackTrace();
            } catch (IOException e) {
                log.error("[结算记录]-excel导出，IO异常");
                e.printStackTrace();
            } finally {
                if (excelWriter != null) {
                    excelWriter.finish();
                }
            }
        }
    }

    private IPage<ParkSettlementRecordExportDto> selectExportPage(SettlementRecordRequest settlementRecordRequest) {
        Page<ParkSettlementRecordExportDto> page = new Page<>();
        page.setCurrent(settlementRecordRequest.getPageNum());
        page.setSize(settlementRecordRequest.getPageSize());
        return baseMapper.selectExportPage(page, settlementRecordRequest);
    }

    private long getCount(SettlementRecordRequest settlementRecordRequest) {
        LambdaQueryWrapper<ParkSettlementRecord> queryWrapper = getLambdaQueryRequest(settlementRecordRequest);
        return count(queryWrapper);
    }

    private IPage<ParkSettlementRecord> selectPage(SettlementRecordRequest settlementRecordRequest) {
        LambdaQueryWrapper<ParkSettlementRecord> queryWrapper = getLambdaQueryRequest(settlementRecordRequest);

        // 分页
        Page<ParkSettlementRecord> pageRequest = new Page<>();
        pageRequest.setCurrent(settlementRecordRequest.getPageNum());
        pageRequest.setSize(settlementRecordRequest.getPageSize());

        return page(pageRequest, queryWrapper);
    }

    private LambdaQueryWrapper<ParkSettlementRecord> getLambdaQueryRequest(SettlementRecordRequest settlementRecordRequest) {
        LambdaQueryWrapper<ParkSettlementRecord> queryWrapper = Wrappers.lambdaQuery();

        queryWrapper.eq(null != settlementRecordRequest.getParkId(), ParkSettlementRecord::getParkId, settlementRecordRequest.getParkId());
        // 结算类型
        queryWrapper.eq(StrUtil.isNotBlank(settlementRecordRequest.getSettlementType()),
                ParkSettlementRecord::getSettlementType, settlementRecordRequest.getSettlementType());
        // 打款状态
        queryWrapper.eq(null != settlementRecordRequest.getPaymentStatus(),
                ParkSettlementRecord::getPaymentStatus, settlementRecordRequest.getPaymentStatus());
        // 结算开始时间
        queryWrapper.ge(StrUtil.isNotBlank(settlementRecordRequest.getSettlementDateStart()),
                ParkSettlementRecord::getSettlementDate, settlementRecordRequest.getSettlementDateStart());
        // 结算结束时间
        queryWrapper.le(StrUtil.isNotBlank(settlementRecordRequest.getSettlementDateEnd()),
                ParkSettlementRecord::getSettlementDate, settlementRecordRequest.getSettlementDateEnd());

        // 排序
        queryWrapper.orderByDesc(ParkSettlementRecord::getSettlementDate);

        return queryWrapper;
    }

    /**
     * 统计金额
     */
    private SettlementStatisticsDto statisticsAmount(SettlementRecordRequest settlementRecordRequest) {
        return parkSettlementRecordMapper.statisticsAmount(settlementRecordRequest);
    }

}
